﻿Imports System.Xml
Imports System.IO

Module Module1

    Dim fileToProcess As String = ""
    Dim output As String = ""
    Dim input As String = ""
   
    Dim attname As String = ""
    Dim release As String = ""
    Dim messageType As String = ""
    Dim baseDepth As String = ""

    Dim filePath As String = ""
    Dim filewriter As StreamWriter

    Dim functional_group_arraylist As New ArrayList

    Dim line As String = ""
    Dim functionalGroup As String = ""
    Dim ignoreOnce As Boolean = False

    Dim inLSloop As Boolean = False
    Dim LSDepth As Integer = 0

    Dim nextSegmentDefinesGroup As Boolean = False
    Dim nextSegmentMin As String = ""
    Dim nextSegmentMax As String = ""
    Dim nextSegmentTABs As String = ""


    Sub Main()

        Try

            Dim min As String = ""
            Dim max As String = ""

            Dim args() As String = Environment.GetCommandLineArgs()
            Dim intArgs As Integer = Environment.GetCommandLineArgs().Length()

            'intArgs = 2

            'it considers itself as the first parameter
            If intArgs <> 2 Then

                Throw (New Exception("Needs 1 arguments: file to process"))

            Else

                '   fileToProcess = "C:\xml2bots\837.Config"
                fileToProcess = args(1)
                'read in the Functional ID's

                Using r As StreamReader = New StreamReader("Functional_Group_List.txt")
                    '  Using r As StreamReader = New StreamReader("c:\xml2bots\Functional_Group_List.txt")

                    ' Read first line.
                    'line = r.ReadLine

                    ' Loop over each line in file, While list is Not Nothing.
                    Do While (Not line Is Nothing)

                        ' Read in the next line.
                        line = r.ReadLine
                        ' Add this line to list.

                        If line Is Nothing Then

                        Else

                            functional_group_arraylist.Add(line)
                            ' Display to console.
                            Console.WriteLine(line)
                        End If

                    Loop

                End Using

                Using reader As XmlReader = XmlReader.Create(fileToProcess)

                    reader.Read()
                    reader.ReadToFollowing("Release")
                    reader.Read()
                    release = "00" & reader.Value

                    reader.ReadToFollowing("MessageType")
                    reader.Read()
                    messageType = reader.Value

                    'find what type of message this is

                    Dim temp As String
                    Dim split(1) As String

                    For Each temp In functional_group_arraylist

                        split = temp.Split(" ")

                        If split(0) = messageType Then
                            functionalGroup = split(1)
                            Exit For
                        End If

                    Next

                    If functionalGroup = "" Then

                        Console.WriteLine("functional group not found for " & fileToProcess)

                        Console.ReadKey(True)

                    End If

                    filePath = messageType & release & ".py"

                    If filePath = "00.py" Then

                        Console.WriteLine(fileToProcess)

                        Console.ReadKey(True)

                    End If

                    If File.Exists(filePath) Then

                        File.Delete(filePath)

                    End If

                    filewriter = New StreamWriter(filePath, True)

                    'write header
                    WriteToFile("from bots.botsconfig import *")
                    WriteToFile("from records" & release & " import recorddefs")
                    WriteToFile("")
                    WriteToFile("syntax = { ")
                    WriteToFile("        'version'    :  '00403',    #version of ISA to send")
                    WriteToFile("        'functionalgroup'    :  '" & functionalGroup & "',")
                    WriteToFile("        }")
                    WriteToFile("")

                    reader.ReadToFollowing("Group")

                    baseDepth = 5

                    While reader.Read

                        input = reader.GetAttribute("name")

                        If input = "Message" Then

                            While reader.Read

                                reader.Read()

                                input = reader.Name

                                If input = "Segment" Then

                                    If Not reader.GetAttribute("ref") = "GE" And Not reader.GetAttribute("ref") = "IEA" Then

                                        min = reader.GetAttribute("minOccurs")
                                        If min = "" Then
                                            min = 1
                                        End If

                                        max = reader.GetAttribute("maxOccurs")
                                        Select Case max

                                            Case Nothing
                                                max = 1

                                            Case "unbounded"
                                                max = 99999

                                        End Select

                                        'output the Segment
                                        Console.WriteLine("structure = [")
                                        Console.WriteLine("{ID: '" & (reader.GetAttribute("ref") & "', MIN: " & min & _
                                                              ", MAX: " & max & ", LEVEL: ["))

                                        WriteToFile("structure = [")
                                        WriteToFile("{ID: '" & (reader.GetAttribute("ref") & "', MIN: " & min & _
                                                              ", MAX: " & max & ", LEVEL: ["))


                                    End If

                                End If

                                checkDeeper(reader)

                            End While

                        End If

                    End While

                End Using

                filewriter.Close()


            End If

        Catch ex As Exception

            Console.WriteLine(ex)

        End Try


    End Sub

    Private Sub checkDeeper(ByVal reader As XmlReader)

        Dim min As String = Nothing
        Dim max As String = Nothing

        Dim input As String = ""
        While reader.Read

            reader.Read()

            'if we are at an end node we want to pop back out! And write the end of the segment

            Select Case reader.NodeType

                Case XmlNodeType.EndElement
                    'this handles the closing of a group element

                    If reader.LocalName = "Message" Then

                        'This closes out the file
                        Console.WriteLine("]}")
                        Console.WriteLine("]")

                        WriteToFile("]}")
                        WriteToFile("]")

                    Else

                        If reader.Depth > baseDepth Then

                            If reader.Depth = LSDepth And inLSloop Then

                                addTabs(reader)
                                Console.WriteLine(output + "{ID: 'LE', MIN: 1, MAX: 1},")
                                WriteToFile(output + "{ID: 'LE', MIN: 1, MAX: 1},")

                                inLSloop = False

                                Console.WriteLine(output + "]},")
                                WriteToFile(output + "]},")

                            Else

                                addTabs(reader)
                                Console.WriteLine(output + "]},")
                                WriteToFile(output + "]},")
                            End If



                        End If

                    End If

                    Exit While

            End Select

            input = reader.Name

            If input = "Segment" Then

                min = Nothing
                max = Nothing

                'lets detect the LS segment and put it in a group, also add LS to the end 

                If reader.GetAttribute("ref") = "LE" Then

                    addTabs(reader)
                    Console.WriteLine(output + "]},")

                    addTabs(reader)
                    WriteToFile(output + "]},")

                ElseIf reader.GetAttribute("ref") = "LS" Then

                    'get our depth to use to get out of this mess
                    LSDepth = reader.Depth

                    min = reader.GetAttribute("minOccurs")
                    If min = "" Then
                        min = 1
                    End If

                    max = reader.GetAttribute("maxOccurs")
                    Select Case max

                        Case Nothing
                            max = 1

                        Case "unbounded"
                            max = 99999

                    End Select

                    attname = reader.GetAttribute("ref")

                    addTabs(reader)
                    Console.WriteLine(output & "{ID: '" & attname & "', MIN: " & min & _
                                          ", MAX: " & max & ", LEVEL: [")

                    WriteToFile(output & "{ID: '" & attname & "', MIN: " & min & _
                                          ", MAX: " & max & ", LEVEL: [")

                    'we are at a group... but is there another group here?

                    inLSloop = True
                    checkDeeper(reader)


                Else

                    min = reader.GetAttribute("minOccurs")
                    max = reader.GetAttribute("maxOccurs")

                    'this is a hardcoded hack, Altova appears to always list the next segment with out any min or max
                    'this is what defines the group

                    If min = "" And max = "" And ignoreOnce Then

                        If min = "" Then

                            min = 1

                        End If

                        Select Case max

                            Case Nothing
                                max = 1

                            Case "unbounded"
                                max = 99999

                        End Select

                        If nextSegmentDefinesGroup Then

                            nextSegmentDefinesGroup = False


                            Console.WriteLine(nextSegmentTABs & "{ID: '" & reader.GetAttribute("ref") & "', MIN: " & nextSegmentMin & _
                                                     ", MAX: " & nextSegmentMax & ", LEVEL: [")

                            WriteToFile(nextSegmentTABs & "{ID: '" & reader.GetAttribute("ref") & "', MIN: " & nextSegmentMin & _
                                                     ", MAX: " & nextSegmentMax & ", LEVEL: [")

                        Else

                            'output the Segment
                            addTabs(reader)
                            Console.WriteLine(output & "{ID: '" & (reader.GetAttribute("ref") & "', MIN: " & min & _
                                             ", MAX: " & max & "},"))

                            WriteToFile(output & "{ID: '" & (reader.GetAttribute("ref") & "', MIN: " & min & _
                                                  ", MAX: " & max & "},"))


                        End If

                    Else

                        ignoreOnce = True
                        If min = "" Then

                            min = 1

                        End If

                        Select Case max

                            Case Nothing
                                max = 1

                            Case "unbounded"
                                max = 99999

                        End Select

                        If nextSegmentDefinesGroup Then

                            nextSegmentDefinesGroup = False

                            Console.WriteLine(nextSegmentTABs & "{ID: '" & reader.GetAttribute("ref") & "', MIN: " & nextSegmentMin & _
                                                     ", MAX: " & nextSegmentMax & ", LEVEL: [")

                            WriteToFile(nextSegmentTABs & "{ID: '" & reader.GetAttribute("ref") & "', MIN: " & nextSegmentMin & _
                                                     ", MAX: " & nextSegmentMax & ", LEVEL: [")

                            
                        Else

                            'output the Segment
                            addTabs(reader)

                            Console.WriteLine(output & "{ID: '" & (reader.GetAttribute("ref") & "', MIN: " & min & _
                                                  ", MAX: " & max & "},"))

                            WriteToFile(output & "{ID: '" & (reader.GetAttribute("ref") & "', MIN: " & min & _
                                                  ", MAX: " & max & "},"))
                        End If

                    End If

                End If

            End If

            If input = "Group" Then

                nextSegmentDefinesGroup = True

                nextSegmentMin = Nothing
                nextSegmentMax = Nothing
                nextSegmentTABs = Nothing

                addTabs(reader)
                nextSegmentTABs = output

                nextSegmentMin = reader.GetAttribute("minOccurs")
                If nextSegmentMin = "" Then
                    nextSegmentMin = 1
                End If

                nextSegmentMax = reader.GetAttribute("maxOccurs")
                Select Case nextSegmentMax

                    Case Nothing
                        nextSegmentMax = 1

                    Case "unbounded"
                        nextSegmentMax = 99999

                End Select

                'we are at a group... but is there another group here?

                checkDeeper(reader)

            End If

        End While

    End Sub

    Private Sub addTabs(ByVal reader As XmlReader)

        'clear anything in the output
        output = ""

        If reader.Depth > baseDepth Then

            Dim tabs As Integer = reader.Depth - baseDepth

            If inLSloop Then tabs = tabs + 1

            For i = 1 To tabs
                output = output & "    "
            Next

        End If

    End Sub

    Private Sub WriteToFile(ByVal line As String)

        filewriter.WriteLine(line)

    End Sub

End Module
